package com.ojoin.trade.common.utils;

import org.apache.commons.lang3.StringUtils;

import com.ojoin.trade.common.exception.BusinessException;


 
public class SMSHelper {

	//手机号：短信验证码存储的Key
    private final static String MOBILEVERIFYSMSCODE = "mobileverifysmscode";
    
    //添加银行卡：短信验证码存储的Key
    private final static String ADDBANKCARDSMSCODE = "addBankCardSMSCode";
    
    //修改账户信息：短信验证码的Key
    private final static String MODIFYACCOUNTINFOSMSCODE = "modifyAccountInfoSMSCode";
    
    // 短信验证码时间戳后缀
    private final static String TIMESTAMP_SUFFIX = "timestamp";
    
    //重试次数后缀
    private final static String RETRY_SUFFIX = "retrycount";
    
    //重试次数(一个周期内 默认一小时)
    private final static int RETRYCOUNT = 3;
    
    /**
     * 短信验证码的超时时间
     */
    private final static long MSG_CODE_OVERTIME = 15 * 60 * 1000;

    private final static String smsRecordCache="smsRecordCache";
    /**
     * 创建指定数量的随机字符串
     * @param numberFlag 是否是数字
     * @param length
     * @return
     */
    public static String createRandomCode(boolean numberFlag, int length){
        String retStr = "";
        String strTable = numberFlag ? "1234567890" : "1234567890abcdefghijkmnpqrstuvwxyz";
        int len = strTable.length();
        boolean bDone = true;
        do {
            retStr = "";
            int count = 0;
            for (int i = 0; i < length; i++) {
                double dblR = Math.random() * len;
                int intR = (int) Math.floor(dblR);
                char c = strTable.charAt(intR);
                if (('0' <= c) && (c <= '9')) {
                    count++;
                }
                retStr += strTable.charAt(intR);
            }
            if (count >= 2) {
                bDone = false;
            }
        } while (bDone);

        return retStr;
    }
    
    public static void sendMobileCode(String merchantno,String mobile,String validateCode){
    	long msgCodeRetryCount=getMobileValidateCodeRetryCount(MOBILEVERIFYSMSCODE,merchantno);
        if(-1!=msgCodeRetryCount){
        	if(msgCodeRetryCount>=RETRYCOUNT)
        		throw new BusinessException("验证码请求超过每天最大次数 "+RETRYCOUNT);
        }
         if(CommonUtils.isDev()) {
        	EmailSendUtil.sendCheckCode(Config.getProperty("mail.dev.receiver"),validateCode);
        }else{
        	SMSSendUtil.sendCheckCode(mobile,validateCode);
        }
		addMobileValidateCodeRetryCount(MOBILEVERIFYSMSCODE,merchantno);
	}
    
    public static boolean validateMobileCode(String merchantno,String shortMsgCode){
        if(StringUtils.isBlank(shortMsgCode)) {
        	return false;
        }
        
        long msgCodeTimestamp = getMobileValidateCodeTimestamp(merchantno);
        if(isMsgCodeOvertime(msgCodeTimestamp)) {
        	return false;
        }
        
        String lastMsgCode = getMobileValidateCode(merchantno);
        boolean ret = lastMsgCode.equals(shortMsgCode);
        if(StringUtils.isBlank(lastMsgCode)||!ret) {
        	return false;
        }

		return ret;
    }
    
    public static void sendModifyAccountInfoCode(String merchantno,String mobile,String validateCode){
    	long msgCodeRetryCount=getMobileValidateCodeRetryCount(MODIFYACCOUNTINFOSMSCODE,merchantno);
        if(-1!=msgCodeRetryCount){
        	if(msgCodeRetryCount>=RETRYCOUNT)
        		throw new BusinessException("验证码请求超过每天最大次数 "+RETRYCOUNT);
        }
        if(CommonUtils.isDev()) {
        	EmailSendUtil.sendCheckCode(Config.getProperty("mail.dev.receiver"),validateCode);
        }else{
        	SMSSendUtil.sendCheckCode(mobile,validateCode);
        }
		addMobileValidateCodeRetryCount(MODIFYACCOUNTINFOSMSCODE,merchantno);
	}
    
    public static boolean validateModifyAccountInfoCode(String merchantno, String shortMsgCode) {
    	if(StringUtils.isBlank(shortMsgCode)) {
    		return false;
    	}
    	
    	long msgCodeTimestamp = getModifyAccountInfoCodeTimestamp(merchantno);
    	if(isMsgCodeOvertime(msgCodeTimestamp)) {
    		return false;
    	}
    	
    	String lastMsgCode = getModifyAccountInfoValidateCode(merchantno);
    	boolean ret = lastMsgCode.equals(shortMsgCode);
        if(StringUtils.isBlank(lastMsgCode)||!ret) {
        	return false;
        }
    	
    	return ret;
    }
    
    public static void sendAddBankCardCode(String merchantno,String mobile,String validateCode){
    	long msgCodeRetryCount=getMobileValidateCodeRetryCount(ADDBANKCARDSMSCODE,merchantno);
        if(-1!=msgCodeRetryCount){
        	if(msgCodeRetryCount>=RETRYCOUNT)
        		throw new BusinessException("验证码请求超过每天最大次数 "+RETRYCOUNT);
        }
        if(CommonUtils.isDev()) {
        	EmailSendUtil.sendCheckCode(Config.getProperty("mail.dev.receiver"),validateCode);
        }else{
        	SMSSendUtil.sendCheckCode(mobile,validateCode);
        }
		addMobileValidateCodeRetryCount(ADDBANKCARDSMSCODE,merchantno);
	}
    
    public static boolean validateAddBankCardCode(String merchantno,String shortMsgCode){
        if(StringUtils.isBlank(shortMsgCode)) {
        	return false;
        }
        
        long msgCodeTimestamp = getAddBankCardCodeTimestamp(merchantno);
        if(isMsgCodeOvertime(msgCodeTimestamp)) {
        	return false;
        }
        
        String lastMsgCode = getAddBankCardValidateCode(merchantno);
        boolean ret = lastMsgCode.equals(shortMsgCode);
        if(StringUtils.isBlank(lastMsgCode)||!ret) {
        	return false;
        }
    	
    	return ret;
    }
    
    
    /**
     * 生成某商户号的某类短信验证码的key
     * @param msgCodeType    短信验证码key
     * @param merchantno    商户号
     * @return    短信验证码的key
     */
    private static String getMobileNoMsgCodeKey(String msgCodeType, String merchantno) {
    	return new StringBuffer().append(msgCodeType).append("_")
    				.append(merchantno).toString();
    }

    /**
     * 生成某商户号的某类短信验证码的时间戳的key
     * 形式为：msgCodeKey_TIMESTAMPSUFFIX_merchantno
     * @param msgCodeType    短信验证码的key
     * @param merchantno    商户号
     * @return
     */
    private static String getCacheTimestampKey(String msgCodeType, String merchantno) {
    	return new StringBuffer().append(msgCodeType).append("_")
    				.append(TIMESTAMP_SUFFIX).append("_")
    				.append(merchantno).toString();
    }
    
    
    private static String getCacheRetryCountKey(String msgCodeType, String merchantno) {
    	return new StringBuffer().append(msgCodeType).append("_")
    				.append(RETRY_SUFFIX).append("_")
    				.append(merchantno).toString();
    }
    
    
    /**
     * 判断短信验证码是否超时
     * 将保存短信验证码时的时间戳与系统当前时间戳作比较，如果当前时间戳与原时间戳的差值大于15min，则视为超时
     * @param msgCodeTimestamp    短信验证码的时间戳
     * @return    超时，true；未超时，false
     */
    private static boolean isMsgCodeOvertime(long msgCodeTimestamp) {
    	long currentTimestamp = System.currentTimeMillis();
    	return ((currentTimestamp - msgCodeTimestamp) <= MSG_CODE_OVERTIME) ? false : true;
    }
    
    /**
     * 清除短信验证码，包括验证码、时间戳
     * @param msgCodeType    短信验证码的key
     * @param merchantno    商户号
     */
    private static void clearMsgValidateCode(String msgCodeType, String merchantno) {
    	// 清除短信验证码
    	String msgCodeKey = getMobileNoMsgCodeKey(msgCodeType, merchantno);
    	CacheUtils.getInstance().delete(smsRecordCache,msgCodeKey);
    	
    	// 清除短信验证码时间戳
    	String msgCodeTimestampKey = getCacheTimestampKey(msgCodeType, merchantno);
    	CacheUtils.getInstance().delete(smsRecordCache,msgCodeTimestampKey);
    }
    
    /**
     * 商户手机号验证
     * @param merchantno
     * @param validateCode
     */
    public static void setMobileValidateCode(String merchantno,String validateCode){
        String shortMsgCodeKey = getMobileNoMsgCodeKey(MOBILEVERIFYSMSCODE, merchantno);
        CacheUtils.getInstance().setString(smsRecordCache,shortMsgCodeKey, validateCode);
        
        String timestampKey = getCacheTimestampKey(MOBILEVERIFYSMSCODE, merchantno);
        CacheUtils.getInstance().setString(smsRecordCache,timestampKey, String.valueOf(System.currentTimeMillis()));
    }
    
    public static String getMobileValidateCode(String merchantno){
        String shortMsgCodeKey = getMobileNoMsgCodeKey(MOBILEVERIFYSMSCODE, merchantno);
        return CacheUtils.getInstance().getString(smsRecordCache,shortMsgCodeKey);
    }
    
    private static long getMobileValidateCodeTimestamp(String merchantno) {
    	String timestampKey = getCacheTimestampKey(MOBILEVERIFYSMSCODE, merchantno);
    	String str = CacheUtils.getInstance().getString(smsRecordCache,timestampKey);
    	if(StringUtils.isEmpty(str)){
    		return 0;
    	}
    	return Long.valueOf(str);
    }
    
    private static int getMobileValidateCodeRetryCount(String type,String merchantno) {
    	String timestampKey = getCacheRetryCountKey(type, merchantno);
    	String str = CacheUtils.getInstance().getString(smsRecordCache,timestampKey);
    	if(StringUtils.isEmpty(str)){
    		return -1;
    	}
    	return Integer.valueOf(str);
    }
    
    private static void addMobileValidateCodeRetryCount(String type,String merchantno) {
    	String timestampKey = getCacheRetryCountKey(type, merchantno);
    	String str = CacheUtils.getInstance().getString(smsRecordCache,timestampKey);
    	if(null==str){
    		str="0";
    	}
    	Integer retryCount = Integer.valueOf(str);
		CacheUtils.getInstance().setString(smsRecordCache,timestampKey,String.valueOf(retryCount+1));
    }
    
    
    public static void clearMobileValidateCode(String merchantno) {
    	clearMsgValidateCode(MOBILEVERIFYSMSCODE, merchantno);
    }

    /**
     * 绑卡手机号验证
     * @param merchantno
     * @param validateCode
     */
    public static void setAddBankCardValidateCode(String merchantno, String validateCode) {
    	String shortMsgCodeKey = getMobileNoMsgCodeKey(ADDBANKCARDSMSCODE, merchantno);
    	CacheUtils.getInstance().setString(smsRecordCache,shortMsgCodeKey, validateCode);
    	
    	String timestampKey = getCacheTimestampKey(ADDBANKCARDSMSCODE, merchantno);
    	CacheUtils.getInstance().setString(smsRecordCache,timestampKey, String.valueOf(System.currentTimeMillis()));
    	
    	
    }
    
    public static String getAddBankCardValidateCode(String merchantno) {
    	String shortMsgCodeKey = getMobileNoMsgCodeKey(ADDBANKCARDSMSCODE, merchantno);
    	return CacheUtils.getInstance().getString(smsRecordCache,shortMsgCodeKey);
    }
    
    private static long getAddBankCardCodeTimestamp(String merchantno) {
    	String timestampKey = getCacheTimestampKey(ADDBANKCARDSMSCODE, merchantno);
    	String str = CacheUtils.getInstance().getString(smsRecordCache,timestampKey);
    	if(StringUtils.isEmpty(str)){
    		return 0;
    	}
    	return Long.valueOf(str);
    }
    
    public static void clearAddBankCardValidateCode(String merchantno) {
    	clearMsgValidateCode(ADDBANKCARDSMSCODE, merchantno);
    }
    
    
    /**
     * 账户变动
     * @param merchantno
     * @param validateCode
     */
    public static void setModifyAccountInfoValidateCode(String merchantno,String validateCode){
        String shortMsgCodeKey = getMobileNoMsgCodeKey(MODIFYACCOUNTINFOSMSCODE, merchantno);
        CacheUtils.getInstance().setString(smsRecordCache,shortMsgCodeKey,validateCode);
        
        String timestampKey = getCacheTimestampKey(MODIFYACCOUNTINFOSMSCODE, merchantno);
        CacheUtils.getInstance().setString(smsRecordCache,timestampKey, String.valueOf(System.currentTimeMillis()));
    }

    public static String getModifyAccountInfoValidateCode(String merchantno){
        String shortMsgCodeKey = getMobileNoMsgCodeKey(MODIFYACCOUNTINFOSMSCODE, merchantno);
        return CacheUtils.getInstance().getString(smsRecordCache,shortMsgCodeKey);
    }
    
    private static long getModifyAccountInfoCodeTimestamp(String merchantno) {
    	String timestampKey = getCacheTimestampKey(MODIFYACCOUNTINFOSMSCODE, merchantno);
    	String str = CacheUtils.getInstance().getString(smsRecordCache,timestampKey);
    	if(StringUtils.isEmpty(str)){
    		return 0;
    	}
    	return Long.valueOf(str);
    }
    
    public static void clearModifyAccountInfoValidateCode(String merchantno) {
    	clearMsgValidateCode(MODIFYACCOUNTINFOSMSCODE, merchantno);
    }
   
}
